use std::fs;
use std::path::PathBuf;
use serde::{Serialize, Deserialize};
use serde_json::{Value, Map};
use tauri::command;
use dirs_next::config_dir;
use crate::controller::frpcapi;
use crate::controller::response::ApiResponse;


#[derive(Debug, Serialize, Deserialize, Clone)]
pub struct AuthConfig {
    pub is_auth: u8,      // 0: 无认证, 1: 开启
    pub user: String,
    pub password: String,
}

#[derive(Debug, Serialize, Deserialize, Clone)]
pub struct AppInfo {
    pub is_first: u8,      // 是否第一次安装
    pub create_time: String,
    pub update_time: String,
    pub version: f32,
    pub r#type: u8,        // 1: 预编译包, 2: 本地编译安装, 3: 远程管理地址
    pub auth: AuthConfig,
    pub status: u8,
}

#[derive(Debug, Serialize, Deserialize, Clone)]
pub struct ServerConfig {
    pub host: String,
    pub port: u16,
}

#[derive(Debug, Serialize, Deserialize, Clone)]
pub struct ProxyConfig {
    #[serde(default)]
    pub id: String,
    pub name: String,
    pub proxy_type: String,      // http https udp tcp stcp sudp
    pub local_ip: String,
    pub local_port: u16,
     #[serde(default)]
    pub remote_port: u16,
    pub custom_domains: Vec<String>,
    #[serde(default)]
    pub status: i32,              // 0: 停止, 1: 开启
}

#[derive(Debug, Serialize, Deserialize, Clone)]
pub struct ClientConfig {
    pub server_addr: String,
    pub server_port: u16,
    pub client_server_type: u8,
    pub client_server_path: String,
    pub client_addr: String,
    pub client_port: u16,
    pub client_user: String,
    pub client_password: String,
    pub client_project: String,
    pub client_go: String,
    pub client_frpc_toml: String,
    pub proxies: Vec<ProxyConfig>,
}

#[derive(Debug, Serialize, Deserialize, Clone)]
pub struct ClientStart {
    pub status: u8,
    pub create_time: String,
    pub update_time: String,
    pub number: i32,
}

#[derive(Debug, Serialize, Deserialize, Clone)]
pub struct FullClientConfig {
    pub config: ClientConfig,
    pub start: ClientStart,
}

#[derive(Debug, Serialize, Deserialize, Clone)]
pub struct AppSettings {
    pub app: AppInfo,
    pub server: ServerConfig,
    pub client: FullClientConfig,
}


// ---------- 配置文件路径 ----------
fn config_file_path() -> PathBuf {
    let mut path = config_dir().unwrap_or_else(|| PathBuf::from("."));
    path.push("frp-tauri"); // 应用子目录
    fs::create_dir_all(&path).ok();
    path.push("setting.json");
    path
}

// ---------- 默认配置 ----------
pub fn default_settings() -> AppSettings {
    AppSettings {
        app: AppInfo {
            is_first: 1,
            status: 0,
            create_time: "2025-01-01 00:00:00".to_string(),
            update_time: "2025-01-01 00:00:00".to_string(),
            version: 0.1,
            r#type: 1,
            auth: AuthConfig {
                is_auth: 0,
                user: "admin".to_string(),
                password: "123456".to_string(),
            },
        },
        server: ServerConfig {
            host: "127.0.0.1".to_string(),
            port: 7000,
        },
        client: FullClientConfig {
            start: ClientStart {
                status: 0,
                create_time: crate::utils::time::get_current_time().to_string(),
                update_time: "0000-00-00 00:00:00".to_string(),
                number: 0,
            },
            config: ClientConfig {
                server_addr: "114.55.115.236".to_string(),
                server_port: 8091,
                client_server_type: 1,
                client_server_path: "".to_string(),
                client_addr: "127.0.0.1".to_string(),
                client_port: 7001,
                client_user: "admin".to_string(),
                client_password: "admin".to_string(),
                client_project: "".to_string(),
                client_go: "go".to_string(),
                client_frpc_toml: frpcapi::frpc_toml_path().to_string_lossy().to_string(),
                proxies: vec![
                    ProxyConfig {
                        id: "000000000000000000000000000001".to_string(),
                        name: "本地".to_string(),
                        proxy_type: "http".to_string(),
                        local_ip: "127.0.0.1".to_string(),
                        local_port: 80,
                        remote_port: 0,
                        custom_domains: vec![
                            "one.frp-tauri.local".to_string(),
                            "one.frp-tauri.local".to_string(),
                        ],
                        status: 1,
                    }
                ],
            }
        }
    }
}

// ---------- 加载配置 ----------
pub fn load_settings() -> Result<AppSettings, String> {
    let file_path = config_file_path();
    if file_path.exists() {
        let data = fs::read_to_string(&file_path).map_err(|e| e.to_string())?;
        let settings = serde_json::from_str::<AppSettings>(&data)
            .unwrap_or_else(|_| {
                let cfg = default_settings();
                let _ = save_settings(&cfg);
                cfg
            });
        Ok(settings)
    } else {
        let cfg = default_settings();
        save_settings(&cfg)?;
        Ok(cfg)
    }
}

// ---------- 保存配置 ----------

pub fn save_settings(settings: &AppSettings) -> Result<(), String> {
    let data = serde_json::to_string_pretty(settings).map_err(|e| e.to_string())?;
    fs::write(config_file_path(), data).map_err(|e| e.to_string())
}


/// 递归合并 new_val 到 base_val
fn merge_value(base_val: &mut Value, new_val: &Value) {
    match (base_val, new_val) {
        (Value::Object(base_map), Value::Object(new_map)) => {
            for (k, v) in new_map {
                if base_map.contains_key(k) {
                    merge_value(base_map.get_mut(k).unwrap(), v);
                } else {
                    base_map.insert(k.clone(), v.clone());
                }
            }
        }
        (base, new) => {
            *base = new.clone();
        }
    }
}

#[command]
pub fn get_setting(path: &str) -> ApiResponse<Value> {
    match load_settings() {
        Ok(settings) => {
            let json_val = match serde_json::to_value(settings) {
                Ok(v) => v,
                Err(e) => return ApiResponse::fail(&format!("序列化配置失败: {}", e), None),
            };

            let parts: Vec<&str> = path.split('.').collect();
            let mut current = &json_val;

            for part in parts {
                if let Value::Object(map) = current {
                    current = match map.get(part) {
                        Some(v) => v,
                        None => return ApiResponse::fail(&format!("路径 {} 不存在", path), None),
                    };
                } else {
                    return ApiResponse::fail(&format!("路径 {} 无效", path), None);
                }
            }

            ApiResponse::ok("success", Some(current.clone()))
        }
        Err(e) => ApiResponse::fail(&format!("读取配置失败: {}", e), None),
    }
}

#[command]
pub fn set_setting(path: &str, value: Value) -> ApiResponse<()> {
    match load_settings() {
        Ok(mut settings) => {
            let mut json_val = match serde_json::to_value(&settings) {
                Ok(v) => v,
                Err(e) => return ApiResponse::fail(&format!("配置序列化失败: {}", e), None),
            };

            let parts: Vec<&str> = path.split('.').collect();
            if parts.is_empty() {
                return ApiResponse::fail("路径不能为空", None);
            }

            let last = parts.last().unwrap();
            let mut current = &mut json_val;

            for part in &parts[..parts.len() - 1] {
                if let Value::Object(map) = current {
                    current = map.entry(part.to_string()).or_insert(Value::Object(Map::new()));
                } else {
                    return ApiResponse::fail(&format!("路径 {} 无效", path), None);
                }
            }

            if let Value::Object(map) = current {
                if let Value::Object(_) = value {
                    let existing = map.entry(last.to_string()).or_insert(Value::Object(Map::new()));
                    merge_value(existing, &value);
                } else {
                    map.insert(last.to_string(), value);
                }
            } else {
                return ApiResponse::fail(&format!("路径 {} 无效", path), None);
            }

            match serde_json::from_value::<AppSettings>(json_val) {
                Ok(updated_settings) => {
                    if let Err(e) = save_settings(&updated_settings) {
                        return ApiResponse::fail(&format!("保存配置失败: {}", e), None);
                    }
                    ApiResponse::ok("success", None)
                }
                Err(e) => ApiResponse::fail(&format!("配置反序列化失败: {}", e), None),
            }
        }
        Err(e) => ApiResponse::fail(&format!("读取配置失败: {}", e), None),
    }
}